﻿using System;
using System.Collections;
using System.Reflection;
using System.Xml.Linq;
using FluentlyXml.Core.Serialization;
using FluentlyXml.Core.Utility;

namespace FluentlyXml.Core.BuiltInSerializers
{
	internal static class SerializationBehaviors
	{
		public static XElement AsArray(ISerializationContext context, object target, PropertyInfo property)
		{
			var rawValue = property.GetValue(target, null);

			var enumerable = (IEnumerable)rawValue;

			var element = new XElement(property.Name);

			foreach (var obj in enumerable)
			{
				var subElement = context.Serialize(obj.GetType(), obj);
				element.Add(subElement);
			}

			return element;
		}

		public static XElement Ignore(ISerializationContext context, object target, PropertyInfo property)
		{
			return null;
		}

		public static XElement AsElement(ISerializationContext context, object target, string name, Func<object, object> getter)
		{
			XElement element = null;

			var rawValue = getter(target);

			if (rawValue != null)
			{
				element = new XElement(name);

				if (rawValue is IConvertible)
				{
					var valueAsString = (string)Convert.ChangeType(rawValue, typeof(string));
					element.Value = valueAsString;
				}
				else
				{
					var contentElement = context.Serialize(rawValue.GetType(), rawValue);

					contentElement.Elements().ForEach(e => element.Add((object) e));
				}
			}

			return element;
		}

		public static PropertySerializer AsElementNamed(string elementName)
		{
			return (c, o, p) =>
			       	{
			       		var element = AsElement(c, o, elementName, obj => p.GetValue(obj, null));
			       		return element;
			       	};
		}
	}
}